//
// originally from ColourContrastAnalyser
// http://juicystudio.com/article/colour-contrast-analyser-firefox-extension.php
//
AccessibilityExtension.ns(function() { with (AccessibilityExtension.LIB) {
AccessibilityExtension.LIB.extend(AccessibilityExtension.LIB,
{
	createContrastElement: function(iType, objElement) {
		objElementDetails = {};
	
		objElementDetails.node = objElement; //Added for AccessExt
		objElementDetails.element = objElement.tagName;
		if(objElement.type != undefined && objElement.type != '') objElementDetails.element = objElementDetails.element + "-" + objElement.type;
		objElementDetails.className = objElement.className;
		objElementDetails.IDName = objElement.id;
		objElementDetails.BGColor = objElement.getAttribute('bgcolor');
		objElementDetails.FGColor = objElement.getAttribute('color');
		objElementDetails.forecolour = getColour(objElement, 'color');
		objElementDetails.backcolour = getColour(objElement, 'background-color');
		objElementDetails.parents = getParentElements(objElement);
		if (iType == 1 || iType == 2)
		{
			objElementDetails.luminosity = getLuminosity(objElementDetails.forecolour, objElementDetails.backcolour);
		}
		if (iType == 1 || iType == 3)
		{
			objElementDetails.colourbrightness = getBrightness(objElementDetails.forecolour, objElementDetails.backcolour);
			objElementDetails.colourdifference = getColourDifference(objElementDetails.forecolour, objElementDetails.backcolour);
		}
		return objElementDetails;
	},
	
	contrastElement: function(iType, node)
	{
		// If there is a text node, add this element to the list
		if (node.firstChild && node.tagName && !node.tagName.match(/script/i))
		{
			if (checkText(node.firstChild))
			{
			//	objElementDetails = createContrastElement(iType, node);
				return createContrastElement(iType, node);
			}
		}
	/* Added 25 May 2007 by maurice.lanselle@get-the.net
	 * Patch to also evaluate INPUT elements which display text which should be legible:
	 *  - buttons (submit, reset, and button), 
	 *  - data entry fields (text, file, password).
	*/
	
		else if (node.tagName && node.tagName.match(/input/i))
		{
			if ((node.type == "submit") || (node.type == "text")|| (node.type == "button")|| (node.type == "reset")|| (node.type == "password")|| (node.type == "file"))
			{
			//	objElementDetails = createContrastElement(iType, node);
				return createContrastElement(iType, node);
			}
		}
		return null;
	},
	
	examineContrast: function(iType, objOriginalBody)
	{
		// iType(1) == all
		// iType(2) == Luminosity
		// iType(3) == AERT
	
		label = document.getElementById("LocaleLabels"); 
	
	// moved to ParseDocumentForColourContrast to allow for frames
	//	var objOriginalBody = thewindow.document.getElementsByTagName('body')[0];
		if (!objOriginalBody)
		{
			return;
		}
	
		var objElements = objOriginalBody.getElementsByTagName('*');
	
		if (!objElements)
		{
			return;
		}
	
		var arElements = [];
		var objChild, objElementDetails;
		var iCounter, objP, objCode;
	
		// Only add the body to the list if there is text that isn't in a container
		if (objOriginalBody.firstChild)
		{
			objChild = objOriginalBody.firstChild;
			if (checkText(objChild))
			{
				var objElementDetails = createContrastElement(1, objOriginalBody);
				arElements.push(objElementDetails);
			}
		}
	
		// Get details for each element in the DOM
		for (iCounter=0; iCounter<objElements.length; iCounter++)
		{
			var node = objElements[iCounter];
			var objElementDetails = contrastElement(iType, objElements[iCounter])
			// Avoid adding duplicate details
			if (objElementDetails != null && !alreadygot(arElements, objElementDetails))
			{
				arElements.push(objElementDetails);
			}
		}
	return arElements;
	},
	
	getColour: function(objElement, strProperty)
	{
		var objColourDetails = {};
		var arColour = getColourParts(objElement, strProperty);
	
		objColourDetails.hexcolour = getHex(objElement, strProperty);
		objColourDetails.red = arColour[0];
		objColourDetails.green = arColour[1];
		objColourDetails.blue = arColour[2];
	
		return objColourDetails;
	},
	
	getColourParts: function(objElement, strProperty)
	{
		var arColour = [];
	
		var objStyle = objElement.ownerDocument.defaultView.getComputedStyle(objElement, null);
		var objColour = objStyle.getPropertyCSSValue(strProperty);
		
		if (objColour && objColour.primitiveType == CSSPrimitiveValue.CSS_RGBCOLOR)
		{
			var objRGB = objColour.getRGBColorValue();
	
			var iRed = parseInt(objRGB.red.getFloatValue(CSSPrimitiveValue.CSS_NUMBER), 10);
			var iGreen = parseInt(objRGB.green.getFloatValue(CSSPrimitiveValue.CSS_NUMBER), 10);
			var iBlue = parseInt(objRGB.blue.getFloatValue(CSSPrimitiveValue.CSS_NUMBER), 10);
			arColour = [iRed, iGreen, iBlue];
		}
		else
		{
			try
			{
				arColour = getColourParts(objElement.parentNode, strProperty);
			}
			catch (err)
			{
				if (strProperty == 'color')
				{
					arColour = [0, 0, 0];
				}
				else
				{
					arColour = [255, 255, 255];
				}
			}
		}
	
		return arColour;
	},
	
	getHex: function(objElement, strProperty)
	{
		var objStyle = objElement.ownerDocument.defaultView.getComputedStyle(objElement, null);
		var objColour = objStyle.getPropertyCSSValue(strProperty);
		var strColour;
	
		if (objColour && objColour.primitiveType == CSSPrimitiveValue.CSS_RGBCOLOR)
		{
			objRGB = objColour.getRGBColorValue();
	
			var strRed = objRGB.red.getFloatValue(CSSPrimitiveValue.CSS_NUMBER).toString(16);
			var strGreen = objRGB.green.getFloatValue(CSSPrimitiveValue.CSS_NUMBER).toString(16);
			var strBlue = objRGB.blue.getFloatValue(CSSPrimitiveValue.CSS_NUMBER).toString(16);
	
			if (strRed.length == 1)
			{
				strRed = '0' + strRed;
			}
	
			if (strGreen.length == 1)
			{
				strGreen = '0' + strGreen;
			}
	
			if (strBlue.length == 1)
			{
				strBlue = '0' + strBlue;
			}
	
			strColour = '#' + strRed + strGreen + strBlue;
		}
		else
		{
			try
			{
				strColour = getHex(objElement.parentNode, strProperty);
			}
			catch (err)
			{
				if (strProperty == 'color')
				{
					strColour = '#000000';
				}
				else
				{
					strColour = '#ffffff';
				}
			}
		}
	
		return strColour;
	},
	
	getBrightness: function(objForeColour, objBackColour)
	{
		var iForegroundBrightness = ((objForeColour.red * 299) + (objForeColour.green * 587) + (objForeColour.blue * 114)) / 1000;
		var iBackgroundBrightness = ((objBackColour.red * 299) + (objBackColour.green * 587) + (objBackColour.blue * 114)) / 1000;
		var iBrightDifference;
		var strBrightResult;
	
		if (iBackgroundBrightness > iForegroundBrightness)
		{
			iBrightDifference = parseInt(iBackgroundBrightness - iForegroundBrightness, 10);
		}
		else
		{
			iBrightDifference = parseInt(iForegroundBrightness - iBackgroundBrightness, 10);
		}
	
		if (iBrightDifference > 125)
		{
			strBrightResult = iBrightDifference; // + " " +label.getString("Pass"); Removed for Access Ext
			return [strBrightResult, 1];
		}
	
		strBrightResult = iBrightDifference; // + " " +label.getString("Fail"); Removed for Access Ext
		return [strBrightResult, 0];
	},
	
	getColourDifference: function(objForeColour, objBackColour)
	{
		var iColourDifference = Math.abs(objBackColour.red - objForeColour.red) + Math.abs(objBackColour.green - objForeColour.green) + Math.abs(objBackColour.blue - objForeColour.blue);
		var strColourResult;
	
		if (iColourDifference > 500)
		{
			strColourResult = iColourDifference; // + " " +label.getString("Pass"); Removed for Access Ext
			return [strColourResult, 1];
		}
	
		strColourResult = iColourDifference; // + " " +label.getString("Fail"); Removed for Access Ext
		return [strColourResult, 0];
	},
	
	getLuminosity: function(objForeColour, objBackColour)
	{
		var fFore, fBack, fL1, fL2, fDifference, strResult;
		var fPlaces = Math.pow(10, 2);
	
		fFore = calculateLuminosity(objForeColour.red, objForeColour.green, objForeColour.blue, 255);
		fBack = calculateLuminosity(objBackColour.red, objBackColour.green, objBackColour.blue, 255);
	
		if (fFore > fBack)
		{
			fL1 = fFore;
			fL2 = fBack;
		}
		else
		{
			fL1 = fBack;
			fL2 = fFore;
		}
	
		fDifference = (fL1 + 0.05) / (fL2 + 0.05);
	
		fDifference = Math.round(fDifference * fPlaces) / fPlaces;
	
		if (fDifference < 3)
		{
			strResult = fDifference;  // + " " + label.getString("Fail"); Removed for Access Ext
			return [strResult, 0];
		}
	
		if (fDifference < 5)
		{
			strResult = fDifference;  // + " " + label.getString("PassCond5"); Removed for Access Ext
			return [strResult, 1];
		}
	
		if (fDifference < 7)
		{
			strResult = fDifference; //+ " " + label.getString("PassCond7"); Removed for Access Ext
			return [strResult, 1];
		}
	
		strResult = fDifference;  // + " " + label.getString("Pass3"); Removed for Access Ext
		return [strResult, 1];
	},
	
	calculateLuminosity: function(fRed, fGreen, fBlue, fFullScale)
	{
		var fRedRGB = fRed / fFullScale;
		var fGreenRGB = fGreen / fFullScale;
		var fBlueRGB = fBlue / fFullScale;
		var fLinearisedRed, fLinearisedGreen, fLinearisedBlue;
	
		if (fRedRGB <= 0.03928)
		{
			fLinearisedRed = fRedRGB / 12.92;
		}
		else
		{
			fLinearisedRed = Math.pow(((fRedRGB + 0.055)/1.055), 2.4);
		}
	
		if (fGreenRGB <= 0.03928)
		{
			fLinearisedGreen = fGreenRGB / 12.92;
		}
		else
		{
			fLinearisedGreen = Math.pow(((fGreenRGB + 0.055)/1.055), 2.4);
		}
	
		if (fBlueRGB <= 0.03928)
		{
			fLinearisedBlue = fBlueRGB / 12.92;
		}
		else
		{
			fLinearisedBlue = Math.pow(((fBlueRGB + 0.055)/1.055), 2.4);
		}
	
		return (0.2126 * fLinearisedRed + 0.7152 * fLinearisedGreen + 0.0722 * fLinearisedBlue);
	},
	
	getParentElements: function(objElement)
	{
		var arElements = [];
		var objParent = objElement;
		var strElementName;
	
		do
		{
			objParent = objParent.parentNode;
			if (objParent.tagName !== undefined)
			{
				strElementName = objParent.tagName;
				if (objParent.id)
				{
					strElementName += '#' + objParent.id;
				}
				if (objParent.className)
				{
					strElementName += '.' + objParent.className.replace(/\s/g, '.');
				}
				if (objParent.getAttribute('bgcolor'))
				{
					strElementName += '.bgcolor=' + objParent.getAttribute('bgcolor');
				}
				if (objParent.getAttribute('color'))
				{
					strElementName += '.color=' + objParent.getAttribute('color');
				}
				arElements.push(strElementName);
			}
		} while (objParent.parentNode);
		arElements.reverse();
	
		return arElements;
	},
	
	alreadygot: function(arElements, objElementDetails)
	{
		for (var iCounter=0; iCounter<arElements.length; iCounter++)
		{
			if (arElements[iCounter].element == objElementDetails.element && arElements[iCounter].className == objElementDetails.className && arElements[iCounter].IDName == objElementDetails.IDName && arElements[iCounter].BGColor == objElementDetails.BGColor && arElements[iCounter].FGColor == objElementDetails.FGColor && sameParents(arElements[iCounter].parents, objElementDetails.parents))
			{
				return true;
			}
		}
	
		return false;
	},
	
	sameParents: function(arFirst, arSecond)
	{
		if (arFirst.length != arSecond.length)
		{
			return false;
		}
	
		for (var iCounter=0; iCounter<arFirst.length; iCounter++)
		{
			if (arFirst[iCounter] != arSecond[iCounter])
			{
				return false;
			}
		}
	
		return true;
	},
	
	checkText: function(objNode)
	{
		do
		{
			if (objNode.nodeType == 3 && objNode.data.replace(/\s+/g, '') !== '')
			{
				return true;
			}
	
			objNode = objNode.nextSibling;
	
		} while (objNode);
	
		return false;
	}
});
}});